/*
 * Copyright (C) Alibaba Cloud Computing
 * All rights reserved.
 */

using System;
using Aliyun.MNS.Internal;
using Aliyun.MNS.Model;
using Aliyun.MNS.Model.Internal.MarshallTransformations;
using Aliyun.MNS.Runtime;
using Aliyun.MNS.Runtime.Internal.Auth;
using Aliyun.MNS.Runtime.Pipeline;
using Aliyun.MNS.Runtime.Pipeline.Handlers;

namespace Aliyun.MNS
{
    /// <summary>
    /// Implementation for accessing MNS
    /// </summary>
    public partial class MNSClient : AliyunServiceClient, IMNS
    {
        #region Constructors

        /// <summary>
        /// Constructs MNSClient with Aliyun Service Credentials.
        /// </summary>
        /// <param name="credentials">Aliyun Service Credentials</param>
        /// <param name="regionEndpoint">The region endpoint to connect.</param>
        public MNSClient(ServiceCredentials credentials, String regionEndpoint)
            : this(credentials, new MNSConfig { RegionEndpoint = new Uri(regionEndpoint) })
        {
        }

        /// <summary>
        /// Constructs MNSClient with Aliyun Service Credentials and an
        /// MNSClient Configuration object.
        /// </summary>
        /// <param name="credentials">Aliyun Service Credentials</param>
        /// <param name="clientConfig">The MNSClient Configuration Object</param>
        public MNSClient(ServiceCredentials credentials, MNSConfig clientConfig)
            : base(credentials, clientConfig)
        {
        }

        /// <summary>
        /// Constructs MNSClient with Aliyun Access Key ID and Aliyun Secret Key
        /// </summary>
        /// <param name="accessKeyId">Aliyun Access Key ID</param>
        /// <param name="secretAccessKey">Aliyun Secret Access Key</param>
        /// <param name="regionEndpoint">The region endpoint to connect. 
        /// http://$AccountID.mns.<region>.aliyuncs.com</param>
        public MNSClient(string accessKeyId, string secretAccessKey, string regionEndpoint)
            : this(accessKeyId, secretAccessKey, new MNSConfig { RegionEndpoint = new Uri(regionEndpoint) })
        {
        }

        /// <summary>
        /// Constructs MNSClient with Aliyun Access Key ID, Secret Access Key and an
        /// MNSClient Configuration object. 
        /// </summary>
        /// <param name="accessKeyId">Aliyun Access Key ID</param>
        /// <param name="secretAccessKey">Aliyun Secret Access Key</param>
        /// <param name="clientConfig">The MNSClient Configuration Object</param>
        public MNSClient(string accessKeyId, string secretAccessKey, MNSConfig clientConfig)
            : base(accessKeyId, secretAccessKey, clientConfig)
        {
        }

        #endregion

        #region Overrides

        protected override IServiceSigner CreateSigner()
        {
            return new MNSSigner();
        }

        protected override void CustomizeRuntimePipeline(RuntimePipeline pipeline)
        {
            pipeline.AddHandlerAfter<Marshaller>(new ResponseValidationHandler());
        }

        #endregion

        #region Dispose

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        #endregion

        #region  CreateQueue

        /// <inheritdoc/>
        public Queue CreateQueue(string queueName)
        {
            var request = new CreateQueueRequest {QueueName = queueName};
            return CreateQueue(request);
        }

        /// <inheritdoc/>
        public Queue CreateQueue(CreateQueueRequest request)
        {
            var marshaller = new CreateQueueRequestMarshaller();
            var unmarshaller = CreateQueueResponseUnmarshaller.Instance;

            var response = Invoke<CreateQueueRequest, CreateQueueResponse>(request, marshaller, unmarshaller);
            return new Queue(response.QueueUrl, this);
        }

        /// <inheritdoc/>
        public IAsyncResult BeginCreateQueue(CreateQueueRequest request, AsyncCallback callback, object state)
        {
            var marshaller = new CreateQueueRequestMarshaller();
            var unmarshaller = CreateQueueResponseUnmarshaller.Instance;

            return BeginInvoke<CreateQueueRequest>(request, marshaller, unmarshaller,
                callback, state);
        }

        /// <inheritdoc/>
        public Queue EndCreateQueue(IAsyncResult asyncResult)
        {
            var response = EndInvoke<CreateQueueResponse>(asyncResult);
            return new Queue(response.QueueUrl, this);
        }

        #endregion

        #region GetNativeQueue

        /// <inheritdoc/>
        public Queue GetNativeQueue(string queueName)
        {
            return new Queue(queueName, this);
        }

        #endregion

        #region  DeleteQueue

        /// <inheritdoc/>
        public DeleteQueueResponse DeleteQueue(string queueName)
        {
            var request = new DeleteQueueRequest { QueueName = queueName };
            return DeleteQueue(request);
        }

        /// <inheritdoc/>
        public DeleteQueueResponse DeleteQueue(DeleteQueueRequest request)
        {
            var marshaller = new DeleteQueueRequestMarshaller();
            var unmarshaller = DeleteQueueResponseUnmarshaller.Instance;

            return Invoke<DeleteQueueRequest,DeleteQueueResponse>(request, marshaller, unmarshaller);
        }

        /// <inheritdoc/>
        public IAsyncResult BeginDeleteQueue(DeleteQueueRequest request, AsyncCallback callback, object state)
        {
            var marshaller = new DeleteQueueRequestMarshaller();
            var unmarshaller = DeleteQueueResponseUnmarshaller.Instance;

            return BeginInvoke<DeleteQueueRequest>(request, marshaller, unmarshaller,
                callback, state);
        }

        /// <inheritdoc/>
        public  DeleteQueueResponse EndDeleteQueue(IAsyncResult asyncResult)
        {
            return EndInvoke<DeleteQueueResponse>(asyncResult);
        }

        #endregion

        #region  ListQueue

        /// <inheritdoc/>
        public ListQueueResponse ListQueue(string queueNamePrefix)
        {
            var request = new ListQueueRequest()
            {
                QueueNamePrefix = queueNamePrefix
            };
            return ListQueue(request);
        }

        /// <inheritdoc/>
        public ListQueueResponse ListQueue(string queueNamePrefix, string marker, uint maxReturns)
        {
            var request = new ListQueueRequest()
            {
                QueueNamePrefix = queueNamePrefix,
                Marker = marker,
                MaxReturns = maxReturns
            };
            return ListQueue(request);
        }

        /// <inheritdoc/>
        public ListQueueResponse ListQueue(ListQueueRequest request)
        {
            var marshaller = new ListQueueRequestMarshaller();
            var unmarshaller = ListQueueResponseUnmarshaller.Instance;

            return Invoke<ListQueueRequest, ListQueueResponse>(request, marshaller, unmarshaller);
        }

        /// <inheritdoc/>
        public IAsyncResult BeginListQueue(ListQueueRequest request, AsyncCallback callback, object state)
        {
            var marshaller = new ListQueueRequestMarshaller();
            var unmarshaller = ListQueueResponseUnmarshaller.Instance;

            return BeginInvoke<ListQueueRequest>(request, marshaller, unmarshaller,
                callback, state);
        }

        /// <inheritdoc/>
        public ListQueueResponse EndListQueue(IAsyncResult asyncResult)
        {
            return EndInvoke<ListQueueResponse>(asyncResult);
        }

        #endregion

    }
}
